package com.seafood.service.impl;

import com.seafood.service.WebSocketService;
import com.seafood.websocket.WebSocketHandler;
import com.seafood.websocket.WebSocketMessage;
import com.seafood.websocket.WebSocketStatistics;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.HashMap;
import java.util.Map;

/**
 * WebSocket服务实现类
 * 
 * @author System
 * @since 2024-01-01
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class WebSocketServiceImpl implements WebSocketService {

    private final WebSocketHandler webSocketHandler;
    private final DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
    
    @Override
    public void sendMessageToUser(Long userId, String type, String content, Object data) {
        log.info("向用户发送消息: userId={}, type={}, content={}", userId, type, content);
        
        WebSocketMessage message = new WebSocketMessage("system", type, content, data);
        webSocketHandler.sendMessageToUser(userId, message);
    }

    @Override
    public void broadcastToTopic(String topic, String type, String content, Object data) {
        log.info("广播消息到主题: topic={}, type={}, content={}", topic, type, content);
        
        WebSocketMessage message = new WebSocketMessage("system", type, content, data, topic);
        webSocketHandler.broadcastToTopic(topic, message);
    }

    @Override
    public void broadcastToAll(String type, String content, Object data) {
        log.info("广播消息到所有客户端: type={}, content={}", type, content);
        
        WebSocketMessage message = new WebSocketMessage("system", type, content, data);
        webSocketHandler.broadcastToAll(message);
    }

    @Override
    public void sendOrderStatusUpdate(Long userId, Long orderId, String status, String message) {
        log.info("发送订单状态更新通知: userId={}, orderId={}, status={}", userId, orderId, status);
        
        Map<String, Object> data = new HashMap<>();
        data.put("orderId", orderId);
        data.put("status", status);
        data.put("updateTime", LocalDateTime.now().format(formatter));
        
        sendMessageToUser(userId, "order_status_update", message, data);
        
        // 同时广播到订单主题
        broadcastToTopic("order_updates", "order_status_update", message, data);
    }

    @Override
    public void sendColdChainAlert(Long userId, String alertType, String message, Object alertData) {
        log.info("发送冷链异常报警通知: userId={}, alertType={}, message={}", userId, alertType, message);
        
        Map<String, Object> data = new HashMap<>();
        data.put("alertType", alertType);
        data.put("alertTime", LocalDateTime.now().format(formatter));
        data.put("alertData", alertData);
        
        if (userId != null) {
            sendMessageToUser(userId, "cold_chain_alert", message, data);
        }
        
        // 同时广播到冷链监控主题
        broadcastToTopic("cold_chain_monitoring", "cold_chain_alert", message, data);
    }

    @Override
    public void sendSystemNotification(String type, String message, Object data) {
        log.info("发送系统通知: type={}, message={}", type, message);
        
        Map<String, Object> notificationData = new HashMap<>();
        notificationData.put("notificationType", type);
        notificationData.put("notificationTime", LocalDateTime.now().format(formatter));
        notificationData.put("data", data);
        
        broadcastToAll("system_notification", message, notificationData);
    }

    @Override
    public void sendStockAlert(Long productId, String productName, Integer currentStock, Integer threshold) {
        log.info("发送产品库存预警: productId={}, productName={}, currentStock={}, threshold={}", 
                productId, productName, currentStock, threshold);
        
        Map<String, Object> data = new HashMap<>();
        data.put("productId", productId);
        data.put("productName", productName);
        data.put("currentStock", currentStock);
        data.put("threshold", threshold);
        data.put("alertTime", LocalDateTime.now().format(formatter));
        
        String message = String.format("产品 [%s] 库存不足，当前库存: %d，预警阈值: %d", 
                productName, currentStock, threshold);
        
        // 广播到库存监控主题
        broadcastToTopic("stock_monitoring", "stock_alert", message, data);
        
        // 同时发送系统通知
        sendSystemNotification("stock_alert", message, data);
    }

    @Override
    public WebSocketStatistics getConnectionStatistics() {
        log.debug("获取WebSocket连接统计信息");
        
        WebSocketStatistics statistics = new WebSocketStatistics();
        statistics.setTotalConnections(webSocketHandler.getConnectionCount());
        statistics.setOnlineUsers(webSocketHandler.getOnlineUserCount());
        statistics.setActiveConnections(webSocketHandler.getConnectionCount());
        statistics.setServerStartTime("2024-01-01 00:00:00"); // 模拟服务器启动时间
        statistics.setLastUpdateTime(LocalDateTime.now().format(formatter));
        
        return statistics;
    }

    /**
     * 发送冷链温度异常警报
     */
    public void sendTemperatureAlert(Long coldChainRecordId, Double currentTemp, Double thresholdMin, Double thresholdMax) {
        log.info("发送温度异常警报: recordId={}, currentTemp={}, threshold=[{}, {}]", 
                coldChainRecordId, currentTemp, thresholdMin, thresholdMax);
        
        Map<String, Object> alertData = new HashMap<>();
        alertData.put("coldChainRecordId", coldChainRecordId);
        alertData.put("currentTemperature", currentTemp);
        alertData.put("thresholdMin", thresholdMin);
        alertData.put("thresholdMax", thresholdMax);
        alertData.put("alertLevel", determineAlertLevel(currentTemp, thresholdMin, thresholdMax));
        
        String message = String.format("冷链温度异常！当前温度: %.2f°C，正常范围: %.2f°C - %.2f°C", 
                currentTemp, thresholdMin, thresholdMax);
        
        sendColdChainAlert(null, "temperature_alert", message, alertData);
    }

    /**
     * 发送湿度异常警报
     */
    public void sendHumidityAlert(Long coldChainRecordId, Double currentHumidity, Double thresholdMin, Double thresholdMax) {
        log.info("发送湿度异常警报: recordId={}, currentHumidity={}, threshold=[{}, {}]", 
                coldChainRecordId, currentHumidity, thresholdMin, thresholdMax);
        
        Map<String, Object> alertData = new HashMap<>();
        alertData.put("coldChainRecordId", coldChainRecordId);
        alertData.put("currentHumidity", currentHumidity);
        alertData.put("thresholdMin", thresholdMin);
        alertData.put("thresholdMax", thresholdMax);
        alertData.put("alertLevel", determineAlertLevel(currentHumidity, thresholdMin, thresholdMax));
        
        String message = String.format("冷链湿度异常！当前湿度: %.2f%%，正常范围: %.2f%% - %.2f%%", 
                currentHumidity, thresholdMin, thresholdMax);
        
        sendColdChainAlert(null, "humidity_alert", message, alertData);
    }

    /**
     * 发送运输状态更新通知
     */
    public void sendTransportStatusUpdate(Long userId, String transportNumber, String status, String location) {
        log.info("发送运输状态更新通知: userId={}, transportNumber={}, status={}, location={}", 
                userId, transportNumber, status, location);
        
        Map<String, Object> data = new HashMap<>();
        data.put("transportNumber", transportNumber);
        data.put("status", status);
        data.put("currentLocation", location);
        data.put("updateTime", LocalDateTime.now().format(formatter));
        
        String message = String.format("运输单 [%s] 状态更新: %s，当前位置: %s", 
                transportNumber, status, location);
        
        if (userId != null) {
            sendMessageToUser(userId, "transport_status_update", message, data);
        }
        
        // 同时广播到物流追踪主题
        broadcastToTopic("logistics_tracking", "transport_status_update", message, data);
    }

    /**
     * 确定警报级别
     */
    private String determineAlertLevel(Double currentValue, Double thresholdMin, Double thresholdMax) {
        if (currentValue == null || thresholdMin == null || thresholdMax == null) {
            return "unknown";
        }
        
        double deviation = 0;
        if (currentValue < thresholdMin) {
            deviation = Math.abs(currentValue - thresholdMin) / thresholdMin;
        } else if (currentValue > thresholdMax) {
            deviation = Math.abs(currentValue - thresholdMax) / thresholdMax;
        }
        
        if (deviation == 0) {
            return "normal";
        } else if (deviation < 0.1) {
            return "warning";
        } else if (deviation < 0.3) {
            return "critical";
        } else {
            return "emergency";
        }
    }
}